package top.hcode.hoj.utils;

import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.URLUtil;
import com.aliyun.oss.OSSClient;
import com.aliyun.oss.common.utils.BinaryUtil;
import com.aliyun.oss.model.*;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.auth.sts.AssumeRoleRequest;
import com.aliyuncs.auth.sts.AssumeRoleResponse;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.http.MethodType;
import com.aliyuncs.http.ProtocolType;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.profile.IClientProfile;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.nutz.json.Json;
import org.nutz.lang.Streams;
import org.nutz.lang.Strings;
import org.nutz.lang.Times;
import org.nutz.lang.util.NutMap;
import top.hcode.hoj.pojo.dto.OssFileInfoDTO;
import top.hcode.hoj.pojo.dto.OssFormUploadDataDTO;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.util.Date;


/**
 * @Author: LiuLin
 * @Date: 2019/3/2 15:39
 */
@Slf4j
public class AliyunOSSUtils {

    private static final String ACCESS_ID = "LTAI5t8rkEuA1A89Ehu29hWu";

    private static final String ACCESS_SECRET = "Kx2X5f4Ko8kWwJ9O2xSWdtTPrqsZF2";

    private static final String BUCKET_NAME = "oistudy";

    private static final String END_POINT = "oss-cn-hangzhou.aliyuncs.com";

    public static final String FILE_DIR = "readlaimg/";

    private static final String POLICY = "{\n" +
            "    \"Statement\": [\n" +
            "        {\n" +
            "            \"Action\": \"sts:AssumeRole\",\n" +
            "            \"Effect\": \"Allow\",\n" +
            "            \"Resource\": \"*\"\n" +
            "        }\n,{\n" +
            "            \"Action\": \"oss:*\",\n" +
            "            \"Effect\": \"Allow\",\n" +
            "            \"Resource\": \"*\"\n" +
            "        }" +
            "    ],\n" +
            "    \"Version\": \"1\"\n" +
            "}";

    private static final ProtocolType PROTOCOL_TYPE = ProtocolType.HTTPS;

    private static final String ROLE_ARN = "acs:ram::1721829999432104:role/ststokenuser";
//    private static final String ROLE_ARN = "acs:ram::1721829999432104:root";


    public static void main(String[] args) {
        String url = "https://oistudy-oss.rui-ya.com/20250103/1875034249782054912.mp4";

        String path = URLUtil.getPath(url);
        System.out.println(path);

        String key = generateFileKey(".md");
        System.out.println(key);

    }

    public static AssumeRoleResponse assumeRole()
            throws RuntimeException {

        try {
            DefaultProfile.addEndpoint("", "", "Sts", END_POINT);
            // 创建一个 Aliyun Acs Client, 用于发起 OpenAPI 请求
            IClientProfile profile = DefaultProfile.getProfile(
                    "cn-hangzhou", ACCESS_ID,
                    ACCESS_SECRET);
            DefaultAcsClient client = new DefaultAcsClient(profile);

            // 创建一个 AssumeRoleRequest 并设置请求参数
            final AssumeRoleRequest request = new AssumeRoleRequest();
            request.setMethod(MethodType.POST);
            request.setProtocol(PROTOCOL_TYPE);

            request.setRoleArn(ROLE_ARN);
            request.setRoleSessionName("test-session");
            request.setPolicy(POLICY);
            //900-3600 15min-1hr
            request.setDurationSeconds(3600L);

            // 发起请求，并得到response
            final AssumeRoleResponse response = client.getAcsResponse(request);
            log.info("Expiration: " + response.getCredentials().getExpiration());
            log.info("Access Key Id: " + response.getCredentials().getAccessKeyId());
            log.info("Access Key Secret: " + response.getCredentials().getAccessKeySecret());
            log.info("Security Token: " + response.getCredentials().getSecurityToken());
            log.info("RequestId: " + response.getRequestId());
            return response;
        } catch (ClientException e) {
            throw new RuntimeException(e.getMessage());
        }
    }

    public static void getOSSClient(String id, String secret, String token) {
        // Endpoint以杭州为例，其它Region请按实际情况填写。
        String endpoint = "http://oss-cn-beijing.aliyuncs.com";


        // 用户拿到STS临时凭证后，通过其中的安全令牌（SecurityToken）和临时访问密钥（AccessKeyId和AccessKeySecret）生成OSSClient。
        // 创建OSSClient实例。注意，这里使用到了上一步生成的STS凭证
        OSSClient ossClient = new OSSClient(endpoint, id, secret, token);


        // OSS操作。
        String content = "Hello OSS";
        ossClient.putObject(BUCKET_NAME, "testHelloOss", new ByteArrayInputStream(content.getBytes()));

        // 关闭OSSClient。
        ossClient.shutdown();
    }

    private static OSSClient ossClient;

    public static OSSClient ossClient() {
        if (ossClient == null) {
            ossClient = new OSSClient(END_POINT, ACCESS_ID, ACCESS_SECRET);
        }

        return ossClient;
    }

    public static String uploadFile(byte[] content, String fileName) {
        try {
            String key = StrUtil.removePrefix(fileName, "/");
            PutObjectRequest putObjectRequest = new PutObjectRequest(BUCKET_NAME, key, new ByteArrayInputStream(content));
            PutObjectResult result = ossClient().putObject(putObjectRequest);
            return "https://oistudy-oss.rui-ya.com/" + key;
        } catch (Exception e) {
            log.error("upload file error", e);
            throw new RuntimeException(e);
        }
    }

    public static String uploadFile(InputStream input, String fileName) {
        byte[] bytes = Streams.readBytesAndClose(input);
        return uploadFile(bytes, fileName);
    }

    public static String uploadFileWithSuffix(byte[] content, String suffix) {
        String key = generateFileKey(suffix);
        return uploadFile(content, key);
    }

    /**
     * 删除文件
     * @param key 可以是url，也可以是key
     */
    public static void deleteFile(String key) {
        try {
            // key https://oistudy-oss.rui-ya.com/20241231/1874090140758925312.jpg
            // key 20241231/1874090140758925312.jpg
            if (key.startsWith("http")) {
                key = StrUtil.removePrefix(URLUtil.getPath(key), "/");
            }
            ossClient().deleteObject(BUCKET_NAME, key);
        } catch (Exception e) {
            log.error("error in AliyunOSSUtils.deleteFile", e);
        }
    }

    public static void renameFile(String oldKey, String newKey) {
        ossClient().copyObject(BUCKET_NAME, oldKey, BUCKET_NAME, newKey);
        ossClient().deleteObject(BUCKET_NAME, oldKey);
    }

    public static String appendImageSmallStyle(String key) {
        if (Strings.isBlank(key) || key.contains("?")) {
            return key;
        }

        return key + "?x-oss-process=style/small";
    }

    /**
     * 生成阿里云oss表单直传签名
     *
     * @param key 上传文件名
     * @return signature
     */
    @SneakyThrows
    public static OssFormUploadDataDTO generatePostSignature(String key) {
        String dir = key;
        if (key.contains("/")) {
            dir = StrUtil.subBefore(key, "/", true) + "/";
        } else {
            dir = StrUtil.sub(key, 0, 8);
        }

        long expireEndTime = System.currentTimeMillis() + 600 * 1000;   // 10min
        Date expiration = new Date(expireEndTime);
        PolicyConditions policyCnds = new PolicyConditions();
        policyCnds.addConditionItem(PolicyConditions.COND_CONTENT_LENGTH_RANGE, 0, 1048576000);
        policyCnds.addConditionItem(MatchMode.StartWith, PolicyConditions.COND_KEY, dir);
        OSSClient client = ossClient();
        String postPolicy = client.generatePostPolicy(expiration, policyCnds);
        byte[] binaryData = postPolicy.getBytes("utf-8");
        String encodedPolicy = BinaryUtil.toBase64String(binaryData);
        String postSignature = client.calculatePostSignature(postPolicy);

        OssFormUploadDataDTO data = new OssFormUploadDataDTO();
        data.setAccessId(ACCESS_ID);
        data.setPolicy(encodedPolicy);
        data.setSignature(postSignature);
        data.setDir(dir);
        data.setKey(key);
        data.setHost("https://oistudy-oss.rui-ya.com");
        return data;
    }

    /**
     * 获取视频信息
     *
     * @param key 视频文件key，例如：20241226/1872282925371867136.mp4
     * @return oss file infos
     */
    @SneakyThrows
    public static OssFileInfoDTO getVideoInfo(String key) {
        // get video url from oss
        GetObjectRequest getObjectRequest = new GetObjectRequest(BUCKET_NAME, key);
        getObjectRequest.setProcess("video/info");

        // 使用getObject方法，并通过process参数传入处理指令。
        OSSObject ossObject = ossClient().getObject(getObjectRequest);
        // 读取并打印视频信息。
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        byte[] buffer = new byte[1024];
        int bytesRead;
        while ((bytesRead = ossObject.getObjectContent().read(buffer)) != -1) {
            baos.write(buffer, 0, bytesRead);
        }
        String infoJson = baos.toString("UTF-8");

        NutMap info = Json.fromJson(NutMap.class, infoJson);
        OssFileInfoDTO dto = new OssFileInfoDTO();
        dto.setFileName(key);
//        dto.setUrl();
//        dto.setType();
        dto.setSize(info.getLong("Size"));
        dto.setDuration(info.getInt("Duration"));

        return dto;
    }

    public static String generateFileKey(String suffix) {
        String ending = StrUtil.prependIfMissing(suffix, ".");
        return Times.format("yyyyMMdd", Times.now()) + "/" + IdUtil.getSnowflakeNextId() + ending;
    }

}
